package com.gmcloud.common.excel.handler;

import com.gmcloud.common.excel.annotation.ResponseExcel;
import org.springframework.core.MethodParameter;
import org.springframework.util.Assert;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @author zl
 * @since  2022/9/20 19:03
 * @BelongsProject gm-cloud
 * @BelongsPackage com.gmcloud.common.handler
 * @description 返回Excel文件的 response 处理器
 */
public class ResponseExcelReturnValueHandler implements HandlerMethodReturnValueHandler {

    private final List<SheetWriteHandler> sheetWriteHandlerList;

    public ResponseExcelReturnValueHandler(List<SheetWriteHandler> sheetWriteHandlerList) {
        this.sheetWriteHandlerList = sheetWriteHandlerList;
    }

    /**
     * 只支持@ResponseExcel 声明的方法
     *
     * @param returnType 方法签名
     * @return 是否支持
     */
    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        return returnType.getMethodAnnotation(ResponseExcel.class) != null;
    }

    /**
     * 处理逻辑
     *
     * @param returnValue  返回参数
     * @param returnType   方法签名
     * @param mavContainer 上下文容器
     * @param webRequest   上下文
     */
    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
        HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
        Assert.state(response != null, "No HttpServletResponse");
        ResponseExcel responseExcel = returnType.getMethodAnnotation(ResponseExcel.class);
        Assert.state(responseExcel != null, "No @ResponseExcel");
        mavContainer.setRequestHandled(true);

        sheetWriteHandlerList.stream().filter(sheetWriteHandler -> sheetWriteHandler.support(returnValue)).findFirst()
                .ifPresent(sheetWriteHandler -> {
                    try {
                        sheetWriteHandler.export(returnValue, response, responseExcel);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                });


    }
}
